<?php
/**
 * Date
 *
 * TO DOC
 *
 * @author  Badrus Said <badrus.said@gmail.com>
 * @protected
 * @singleton
 */
final class api_Date extends Wrapper {
    /**
     * Get number of days for given month and year.
     *
     * @param $a        month
     * @param $b        year
     *
     * @return integer  number of days (28, 29, 30 or 31)
     */
    public function getDays($a, $b) {
       return $a == 2 ? ($b % 4 ? 28 : ($b % 100 ? 29 : ($b % 400 ? 28 : 29))) : (($a - 1) % 7 % 2 ? 30 : 31);
    }

    /**
     * Check if a given year is leap or not.
     *
     * @param $a        year
     *
     * @return boolean  true is leap, not otherwise
     */
    public function isLeapYear($a) {
        return ($a % 4 == 0) ? (($a % 100 == 0) ? (($a % 400 == 0) ? true : false) : true) : false;
    }

    /**
     * Get days for given month
     *
     * @param $a        month
     *
     * @return integer  number of days for given month
     */
    public function daysOfMonth($a) {
        $b = split("[/.-]", $a);
        $m = intval($b[1]);
        $y = intval($b[2]);
        return (in_array($m, array(1, 3, 5, 7, 8, 10, 12))) ? 31 : (($m == 2) ? ((self::isLeap($y)) ? 29 : 28) : 30);
    }

    /**
     * Increment days for given date
     *
     * @param $a        number of days
     *
     * @return new date
     */
    public function incDay($a) {
        $b = preg_split("/([\/\.-])/", $a, -1, PREG_SPLIT_DELIM_CAPTURE);
        $d = intval($b[0]) + 1;
        $m = intval($b[2]);
        $y = intval($b[4]);
        if ($d > self::daysOfMonth($a)) {
            $d = 1;
            $m+= 1;
            if ($m > 12) {
                $m = 1;
                $y+= 1;
            }
        }
        return implode($b[1], array($d, $m, $y));
    }

    /**
     * Decrement days for given date
     *
     * @param $a        number of days
     *
     * @return new date
     */
    public function decDay($a) {
        $b = preg_split("/([\/\.-])/", $a, -1, PREG_SPLIT_DELIM_CAPTURE);
        $d = intval($b[0]) - 1;
        $m = intval($b[2]);
        $y = intval($b[4]);
        if ($d < 1) {
            $e = self::decMonth($a);
            $f = split("[/.-]", $e);
            $d = self::daysOfMonth($e);
            $m = $f[1];
            $y = $f[2];
        }
        return implode($b[1], array($d, $m, $y));
    }

    /**
     * Increment month for given date
     *
     * @param $a        number of months
     *
     * @return new date
     */
    public function incMonth($a) {
        $b = preg_split("/([\/\.-])/", $a, -1, PREG_SPLIT_DELIM_CAPTURE);
        $d = intval($b[0]);
        $m = intval($b[2]) + 1;
        $y = intval($b[4]);
        if ($m > 12) {
            $m = 1;
            $y+= 1;
        }
        return implode($b[1], array($d, $m, $y));
    }

    /**
     * Decrement month for given date
     *
     * @param $a        number of months
     *
     * @return new date
     */
    public function decMonth($a) {
        $b = preg_split("/([\/\.-])/", $a, -1, PREG_SPLIT_DELIM_CAPTURE);
        $d = intval($b[0]);
        $m = intval($b[2]) - 1;
        $y = intval($b[4]);
        if ($m < 1) {
            $m = 12;
            $y-= 1;
        }
        return implode($b[1], array($d, $m, $y));
    }

    /**
     * Fix year format (4 digit) for given year
     *
     * @param $a        year to fix
     *
     * @return fixed year
     */
    public function fixYear($a)  {
        if ($a > 100) return $a;
        $b = intval(date("Y"));
        $c = intval($b / 100);
        $d = ($b % 100 > 50) ? $c : ($c - 1);
        $e = (($d == $c) ? ($c + 1) : $c) * 100;
        return (($a + $e) < $b + 30) ? ($a + $e) : ($a + $d * 100);
    }

    /**
     * Add days for given date
     *
     * @param $a        date to sub
     * @param $n        number days
     *
     * @return new Date
     */
    public function subDaysFromDate($a, $n) {
        $b = preg_split("/([\/\.-])/", $a, -1, PREG_SPLIT_DELIM_CAPTURE);
        return date(
            implode($b[1], array("d", "m", "Y")), strtotime($a) - ($n * 24 * 3600)
        );
    }

    /**
     * Sub days for given date
     *
     * @param $a        date to add
     * @param $n        number days
     *
     * @return new Date
     */
    public function addDaysToDate($a, $n) {
        $b = preg_split("/([\/\.-])/", $a, -1, PREG_SPLIT_DELIM_CAPTURE);
        return date(
            implode($b[1], array("d", "m", "Y")), strtotime($a) + ($n * 24 * 3600)
        );
    }

    /**
     * Sub days for given date
     *
     * @param $a        date to check
     * @param $n        date format
     *
     * @return new Date
     */
    public function check($a, $n = "Y-m-d") {
        $b = preg_split("/([\/\.-])/", $a, -1, PREG_SPLIT_DELIM_CAPTURE);
        $c = array_flip(preg_split("/([\/\.-])/", $n, -1, PREG_SPLIT_DELIM_CAPTURE));
        $y = (isset($c["Y"])) ? $c["Y"] : -1;
        $m = (isset($c["m"])) ? $c["m"] : -1;
        $d = (isset($c["d"])) ? $c["d"] : -1;
        return checkdate(
            (isset($b[$m])) ? $b[$m] : 0, (isset($b[$d])) ? $b[$d] : 0, (isset($b[$y])) ? $b[$y] : 0
        );
    }
}
?>